package ocr

import (
	"bufio"
	"context"
	"encoding/base64"
	"fmt"
	"github.com/google/uuid"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"io"
	"ocr/go_client/dto"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

func Ocr(imageUrl, lang string, isLocal, isAngleCls bool, version int) (*dto.ResultResponse, error) {
	if lang == "" {
		lang = "ch"
	}
	useAngleCls := "false"
	if isAngleCls {
		useAngleCls = "true"
	}
	if isLocal {
		defer os.Remove(imageUrl)
	}
	PpOcr := "PP-OCRv3"
	if version == 4 {
		PpOcr = "PP-OCRv4"
	}
	var cmd *exec.Cmd
	ctx := context.Background()
	if lang == "" {
		cmd = exec.CommandContext(ctx, "paddleocr", "--image_dir", imageUrl, "--use_angle_cls", useAngleCls, "--use_gpu", "false", "--ocr_version", PpOcr)
	} else {
		cmd = exec.CommandContext(ctx, "paddleocr", "--image_dir", imageUrl, "--use_angle_cls", useAngleCls, "--use_gpu", "false", "--ocr_version", PpOcr, "--lang", lang)
	}
	out, err := cmd.StdoutPipe()
	if err != nil {
		return nil, err
	}
	defer out.Close()
	if err = cmd.Start(); err != nil {
		return nil, err
	}
	reader := bufio.NewReader(out)
	res := new(dto.ResultResponse)
	for {
		line, _, err := reader.ReadLine()
		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, err
		}
		s := string(line)
		switch {
		case strings.Contains(s, "ppocr INFO:"): // 包名 版本 版本号
			if !strings.Contains(s, "********") {
				outLine := strings.Split(s, "ppocr INFO:")
				content := outLine[1]
				// 匹配坐标和描述信息的正则表达式
				re := regexp.MustCompile(`\[\[\[(\d+\.\d+), (\d+\.\d+)\], \[(\d+\.\d+), (\d+\.\d+)\], \[(\d+\.\d+), (\d+\.\d+)\], \[(\d+\.\d+), (\d+\.\d+)\]\], \('(.+)', (\d+\.\d+)\)\]`)
				// 使用正则表达式查找匹配的字符串
				matches := re.FindStringSubmatch(content)
				// 打印匹配的结果
				if len(matches) > 0 {
					x1, y1 := matches[1], matches[2]
					x2, y2 := matches[3], matches[4]
					x3, y3 := matches[5], matches[6]
					x4, y4 := matches[7], matches[8]
					description := matches[9]
					damage := matches[10]
					fmt.Printf("坐标: (%s, %s), (%s, %s), (%s, %s), (%s, %s)\n", x1, y1, x2, y2, x3, y3, x4, y4)
					fmt.Printf("描述信息: %s\n", description)
					fmt.Printf("可信度: %s\n", damage)
					res.Content += description
					res.Words = append(res.Words, dto.WordResponse{
						Word: description,
						Figure: []dto.OutputFigureResponse{
							{
								X: x1,
								Y: y1,
							},
							{
								X: x2,
								Y: y2,
							},
							{
								X: x3,
								Y: y3,
							},
							{
								X: x4,
								Y: y4,
							},
						},
						Prob: damage,
					})
				} else {
					fmt.Println("No match found.")
				}
			}
		}
	}
	return res, nil
}

func isJPEG(data []byte) bool {
	return len(data) >= 2 && data[0] == 0xFF && data[1] == 0xD8 // JPEG标志位
}

func isPNG(data []byte) bool {
	return len(data) >= 8 && data[1] == 'P' && data[2] == 'N' && data[3] == 'G' && data[4] == '\r' && data[5] == '\n' && data[6] == 0x1A && data[7] == '\n' // PNG标志位
}

func SaveBase64Image(imageBase64 string) (string, error) {
	//log.Info("imageData", log.Content{"data": imageBase64})
	imageData, err := base64.StdEncoding.DecodeString(imageBase64)
	if err != nil {
		return "", err
	}
	isPng := false
	if isPNG(imageData) {
		isPng = true
	}
	uuidStr := uuid.New().String()
	filename := "/app/imgs/" + uuidStr + ".jpg"
	if isPng {
		filename = "/app/imgs/" + uuidStr + ".png"
	}
	if err = os.WriteFile(filename, imageData, 0666); err != nil {
		return "", err
	}
	return filename, nil
}
